package top.ply.authservice.service.impl;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import top.ply.authservice.dao.StatusMapper;
import top.ply.authservice.dao.WechatUserMapper;
import top.ply.authservice.pojo.Status;
import top.ply.authservice.pojo.WechatUser;
import top.ply.authservice.service.WechatLoginWorker;
import top.ply.common_unit.global_resp.RespUtil;
import top.ply.common_unit.network.NetWork;
import top.ply.common_unit.token.JWTUtil;

import java.util.HashMap;
import java.util.Map;

@Service("wechatLoginWorker")
@RefreshScope
public class WechatLoginWorkerImpl extends BaseAuthService implements WechatLoginWorker {

    Logger logger = LoggerFactory.getLogger(WechatLoginWorkerImpl.class);

    @Autowired
    WechatUserMapper wechatUserMapper;

    @Autowired
    StatusMapper statusMapper;

    @Value("${weixin.code2session.url}")
    private String code2sessionURL;

    @Value("${weixin.appid}")
    private String appid;

    @Value("${weixin.secret}")
    private String wechatSecret;

    private Integer failReason;

    public static final Integer ILLEGAL_PARAMETER = 1;

    public static final Integer USER_STATUS_ERROR = 2;

    @Override
    public String getUserIDFromToken(String token) {
        Map<String, String> payload = JWTUtil.getPayload(token, authServiceSecretKey);
        if (payload == null) {
            return null;
        } else {
            return payload.get(PAYLOAD_USER_ID_KEY);
        }
    }

    @Override
    public boolean accountIsNormal(String userID) {

        Map<String, Object> data = new HashMap<>();

        Thread getNormalCodeThread = new Thread(() -> {
            Integer code = statusMapper.getNormalStatusCode();
            data.put("status_code", code);
        });

        Thread getWechatUserThread = new Thread(() -> {
            WechatUser wechatUser = wechatUserMapper.getWechatUserByUserID(userID);
            data.put("user", wechatUser);
        });

        getNormalCodeThread.start();
        getWechatUserThread.start();

        try {
            getNormalCodeThread.join(1000);
            getWechatUserThread.join(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        if (data.get("status_code") == null || data.get("user") == null) {
            return false;
        } else {
            return ((WechatUser) data.get("user")).getStatus().getStatusCode().equals(data.get("status_code"));
        }
    }

    @Override
    public String wechatUserLogin(String js_code) {
        boolean illegal = checkParam(js_code);  // 检验参数
        if (!illegal) {
            failReason = ILLEGAL_PARAMETER;
            return null;
        }

        Map<String, String> resp = sendToWechatServer(js_code); // 向微信服务器换取openid和session_key

        if (resp.containsKey("openid")) {
            String openid = resp.get("openid");
            WechatUser wechatUser = wechatUserMapper.getWechatUserByOpenId(openid);
            Integer normalCode = statusMapper.getNormalStatusCode();
            String userID;
            if (wechatUser == null) { // 数据库不存在该openid
                userID = generateUserID(openid);
                try {
                    saveWechatUser(userID, openid, normalCode);
                } catch (Exception ignore){
                    logger.error("save to database error: {}", ignore.getMessage());
                }
            } else { // 数据库存在openid
                if (!wechatUser.getStatus().getStatusCode().equals(normalCode)) { // 用户状态异常
                    failReason = USER_STATUS_ERROR;
                    return null;
                } else {
                    userID = wechatUser.getUserID();
                }
            }

            Map<String, String> payload = new HashMap<>();
            payload.put(PAYLOAD_USER_ID_KEY, userID);
            return JWTUtil.createToken(payload, authServiceSecretKey, authServiceTokenExpireTime);
        } else {
            failReason = ILLEGAL_PARAMETER;
            return null;
        }
    }

    public boolean checkParam(String...args) {
        for (String arg : args) {
            if (!StringUtils.hasText(arg)) {
                return false;
            }
        }
        return true;
    }

    public Map<String, String> sendToWechatServer(String js_code) {
        Map<String, String> params = new HashMap<>();
        params.put("appid", appid);
        params.put("secret", wechatSecret);
        params.put("js_code", js_code);
        params.put("grant_type", "authorization_code");
        Map<String, String> resp = NetWork.doGet(code2sessionURL, params, null);
        return resp;
    }

    @Override
    boolean isExists(String userID) {
        return wechatUserMapper.getWechatUserByUserID(userID) != null;
    }

    @Transactional
    public void saveWechatUser(String userID, String openid, Integer statusCode) {
        WechatUser wechatUser = wrapWechatUser(userID, openid, statusCode);
        wechatUserMapper.addWechatUser(wechatUser);
    }

    private WechatUser wrapWechatUser(String userID, String openid, Integer statusCode) {
        WechatUser wechatUser = new WechatUser();
        Status status = new Status();
        status.setStatusCode(statusCode);
        wechatUser.setStatus(status);
        wechatUser.setUserID(userID);
        wechatUser.setOpenid(openid);
        return wechatUser;
    }

    public Integer getFailReason() {
        return failReason;
    }
}
